1 module cgi.router;
2 /*****************************************************************************
3  * package: cgi
4  * module cgi.router
5  * File: router.d
6  * Description:  utility d module that allows conditional execution of classes that implement the ROUTE interface by 
7  * 				 matching a string to the CGI PATH_INFO or QUERY_STRING.
8  * Author: Joseph M. Rice (ricejm01@gmail.com)
9  * Date: Thu Nov 13 13:59:10 EST 2015
10  *
11  *MIT License
12  *
13  *Copyright (c) 2014-2016 Joseph M. Rice <ricejm01@gmail.com>
14  *
15  *Permission is hereby granted, free of charge, to any person obtaining a copy
16  *of this software and associated documentation files (the "Software"), to deal
17  *in the Software without restriction, including without limitation the rights
18  *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19  *copies of the Software, and to permit persons to whom the Software is
20  *furnished to do so, subject to the following conditions:
21  *
22  *The above copyright notice and this permission notice shall be included in all
23  *copies or substantial portions of the Software.
24  *
25  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29  *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30  *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  *SOFTWARE. 
32  ***************************************************************************/
33 
34 import cgi.cgi;
35 import std.algorithm;
36 
37 class RouterException : Exception
38 {
39 	this(string msg, string file = __FILE__, ulong line = cast(ulong)__LINE__, Throwable next = null)
40 	{
41 		super(msg,file,line,next);
42 	}
43 }
44 
45 /**
46  * interface ROUTE
47  *
48  * interface class that allows you to create classes to be used 
49  * with the ROUTER class.   
50  */
51 interface ROUTE 
52 {
53 	/**
54 	 * main method that will perform the actions/purpose of your class.   
55 	 * 
56 	 */
57 	void run(CGI cgi);
58 }
59 
60 /**
61  * class ROUTER
62  *
63  * Description: handle path_info or CGI query string information to logically
64  *      determine a cgi application flow control.  This class allows you use develop
65  *		a restful api, and then serve up content based upon the path_info or CGI 
66  *		query string information.   IE.  "/foo/" or "?func=foo"
67  */
68 class ROUTER
69 {
70 	CGI cgi;
71 	private string path;
72 
73 	this(CGI cgi) {
74 		// Constructor code
75 		if (!cgi) throw new RouterException("cgi environment is not initialized or is null");
76 		this.cgi = cgi;
77 	}
78 
79 	/**
80   	 * run a route based off the path_info envirement variable
81 	 *
82 	 * returns true if the a cgi.PATH_INFO starts with the path variable 
83 	 */	 
84 	bool runRoute(string path, ROUTE route) {
85 		ulong i = 0;
86 		bool pathMatch = false;
87 
88 		if (!path || path.length == 0) throw new RouterException("Un-initialized or null path");
89 
90 		this.path = path;
91 
92 		if (!route) throw new RouterException("Un-initialized or null route");
93 
94 		if (startsWith(cgi.PATH_INFO,path)) pathMatch = true;
95 
96 		if (pathMatch) route.run(cgi);
97 
98 		return pathMatch;
99 	}
100 
101 	/**
102 	 * Run a route based off if a cgi variable exists in a query string.
103 	 *
104 	 * returns true if the name variable exists in the cgi query string.
105 	 */
106 	bool runQueryRoute(string name, ROUTE route) {
107 		bool match = false;
108 
109 		if (!route) throw new RouterException("Un-initialized or null route");
110 
111 		if (cgi.exists(name)) {
112 			route.run(cgi);
113 			match = true;
114 		}
115 
116 		return match;
117 	}
118 
119 	string basePath() {
120 		return this.path;
121 	}
122 }
123